package com.roberto.main;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
import com.roberto.entities.Invader;
import com.roberto.entities.Player;
import com.roberto.entities.Shield;
import com.roberto.entities.Shot;
import com.roberto.entities.UFO;

/**
 * The main class that was used before refactoring, which have been made by design of one of libGDX examples
 *
 * @deprecated
 */
public class Display extends Game {
    public static final int MARGIN = 50;
    private static final String THE_END = "GAME OVER";
    private SpriteBatch batch;
    private Player player;
    private OrthographicCamera camera;
    private static UFO ufo;
    protected static Array<Shot> bullets;
    private static Invader[] invaders;
    private static Shield[] shields = new Shield[4];
    protected static Texture megaTexture;
    private static Texture background;
    private static Sprite backgroundSprite;
    private long tick = TimeUtils.millis(), diedTick, tick2, gameOverTick;
    public int score = 0;
    public static boolean playerMayShot;
    private boolean invaderJustDied;
    private boolean moveDown;
    private boolean running = false;
    private boolean gameOver = false;
    private ShapeRenderer rect;
    private Rectangle invaderBounds, bulletBounds, playersBounds;
    private BitmapFont font;
    private CharSequence livesString = "LIVES", scoreString = "SCORE", gameOverString = "G";
    private Sprite[] livesSprite;
    private boolean delayPermission;
    private int step = 10, gameOverLength = 0;
    private float minX, maxX, minY;
    private float rate = 650, speed, dead;

    public void create() {
        camera = new OrthographicCamera();
        camera.setToOrtho(false, Main.WIDTH, Main.HEIGHT);
        batch = new SpriteBatch();
        rect = new ShapeRenderer();

        megaTexture = new Texture(Gdx.files.internal("res/textures/MegaTexture.png"), Format.RGBA4444, true);
        // megaTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
        // megaTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear);
        megaTexture.setFilter(TextureFilter.Nearest, TextureFilter.MipMapLinearNearest);
        background = new Texture(Gdx.files.internal("res/textures/background.png"), Format.RGB888, true);
        backgroundSprite = new Sprite(background);
        backgroundSprite.rotate90(false);
        backgroundSprite.setSize(Main.WIDTH, Main.HEIGHT);

        player = new Player();
        bullets = new Array<Shot>();
        ufo = new UFO();
        createInvaders();
        createShields();
        livesSprite = new Sprite[player.lives];
        font = new BitmapFont(Gdx.files.internal("res/arcade.fnt"), Gdx.files.internal("res/arcade.png"), false);
        speed = 184 * 2;
        playerMayShot = true;
        running = true;

        // System.out.println(Gdx.app.getJavaHeap());
    }

    public void render() {
        gameLogic();

        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        camera.update();
        font.setColor(Color.WHITE);
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        backgroundSprite.draw(batch);
        player.getSprite().draw(batch);
        if (!gameOver) {

            for (Invader invader : invaders) {
                if (!invader.isDestroyed()) {
                    invader.getSprite().draw(batch);
                }
            }
            if (running) {
                for (Shot bullet : bullets) {
                    bullet.getSprite().draw(batch);
                }
            }

            if (invaderJustDied) {
                Invader.invExplosion.draw(batch);
                if (TimeUtils.millis() - diedTick >= 250) {
                    invaderJustDied = false;
                }
            }
            if (ufo.onGameField() && running) {
                ufo.getSprite().draw(batch);
            }
        } else {
            font.setScale(3);
            font.draw(batch, gameOverString, Main.WIDTH / 2 - 300, Main.HEIGHT / 2 + font.getLineHeight());
            if (TimeUtils.millis() - gameOverTick >= 200) {
                gameOverString = THE_END.subSequence(0, gameOverLength);
                gameOverLength = gameOverLength == THE_END.length() ? THE_END.length() : ++gameOverLength;
                gameOverTick = TimeUtils.millis();
            }
        }
        for (Shield shield : shields) {
            for (int i = 0; i < 10; i++) {
                shield.getSprite(i).draw(batch);
            }

        }
        font.setScale(1);
        font.draw(batch, livesString, Main.WIDTH - 350, Main.HEIGHT - 9);
        font.draw(batch, scoreString, MARGIN + 5, Main.HEIGHT - 9);
        font.setColor(Color.GREEN);
        font.draw(batch, score + "", MARGIN + 170, Main.HEIGHT - 9);

        for (int i = 0; i < player.lives; i++) {
            livesSprite[i] = player.getAliveSprite();
            livesSprite[i].setPosition(800 + (60 * i), Main.HEIGHT - 32);
            livesSprite[i].draw(batch);

        }

        batch.end();
        rect.begin(ShapeType.FilledRectangle);
        rect.setColor(Color.GREEN);
        rect.filledRect(MARGIN, 30, Main.WIDTH - MARGIN * 2, 3);
        // rect.filledRect(MARGIN, 0, 3, Main.HEIGHT);
        // rect.filledRect( Main.WIDTH - MARGIN, 0, 3, Main.HEIGHT);

        rect.end();
        // log.log();

    }

    private void gameLogic() {
        if (running) {
            // player.handleInput();

            if (TimeUtils.millis() - tick >= rate) {
                tick = TimeUtils.millis();
                moveInvaders();
                Invader.playSound();
            }

            // ufo.move();
            rate = rate <= 0 ? 0 : 1000 - speed - dead * 4;

            if (delayPermission && TimeUtils.millis() - tick2 >= 150) {
                playerMayShot = true;
                delayPermission = false;
            }

            if ((rate + 8) * Math.random() < 400) {
                int index;
                do {
                    index = (int) (Math.random() * (invaders.length - 1));
                } while (invaders[index].isDestroyed());
                // bullets.add(new Shot(invaders[index].x, minY - 15, false, invaders[index].getID()));
            }
            checkCollision();
        }

        if (player.isDestroyed() && !gameOver && TimeUtils.millis() - tick >= 650) {
            resume();
            player.revive();

        }

    }

    private void checkCollision() {
        shotsLoop: for (int i = 0; i < bullets.size; i++) {
            bulletBounds = bullets.get(i).getBounds();
            playersBounds = player.getBounds();

            for (Invader invader : invaders) {
                invaderBounds = invader.getBounds();

                if (bullets.get(i).isPlayers() && bulletBounds.overlaps(invaderBounds)) {
                    if (bullets.get(i).isPlayers() && !invader.isDestroyed()) {
                        invader.destroy();
                        bullets.removeIndex(i);
                        playerMayShot = true;
                        Invader.invExplosion.setPosition(invader.x, invader.y);
                        Invader.invExplosion.setSize(invader.width, invader.height);
                        diedTick = TimeUtils.millis();
                        invaderJustDied = true;
                        dead++;
                        switch (invader.getID()) {
                        case 1:
                            score += 40;
                            break;
                        case 2:
                        case 3:
                            score += 20;
                            break;
                        default:
                            score += 10;
                            break;
                        }
                        break shotsLoop;
                    }
                }
            }

            if (!bullets.get(i).isPlayers() && bulletBounds.overlaps(playersBounds)) {
                player.destroy();
                if (player.lives > 1) {
                    player.lives--;
                    pause();
                    tick = TimeUtils.millis();
                } else {
                    player.lives--;
                    gameOver = true;
                    pause();
                }
                bullets.removeIndex(i);
                break;
            }
            for (Shield shield : shields) {
                for (int j = 0; j < 10; j++) {
                    if (shield.getBounds(j).overlaps(bulletBounds)) {
                        shield.damageZone(j);
                        if (bullets.get(i).isPlayers()) {
                            delayPermission = true;
                            tick2 = TimeUtils.millis();
                        }
                        bullets.removeIndex(i);
                        break shotsLoop;
                    }
                }
            }
            if (ufo.onGameField() && ufo.getBounds().overlaps(bulletBounds)) {
                ufo.destroy();
                score += (int) (Math.random() * 6) * 50 + 100;
            }

            if (bullets.get(i).y <= 30 || bullets.get(i).y >= Main.HEIGHT) {
                if (bullets.get(i).isPlayers()) {
                    playerMayShot = true;
                }
                bullets.removeIndex(i);

            }

        }
    }

    private void moveInvaders() {
        minX = Main.WIDTH;
        maxX = 0;
        minY = Main.HEIGHT;
        for (Invader invader : invaders) {
            if (moveDown) {
                invader.move(step, true);
            } else {
                invader.move(step, false);
            }
            if (!invader.isDestroyed()) {
                minX = Math.min(minX, invader.x);
                minY = Math.min(minY, invader.y);
                if (maxX < invader.x + invader.width) {
                    maxX = invader.x + invader.width;
                }
            }

        }
        if (!moveDown && (maxX >= Main.WIDTH - MARGIN - step / 2 || minX <= MARGIN)) {
            moveDown = true;
            step = -step;
            speed += 30;
        } else {
            moveDown = false;
        }

    }

    private void createInvaders() {
        invaders = new Invader[5 * 11];
        int x = 0;
        int y = 0;
        for (int i = 0; i < invaders.length; i++) {
            x++;
            if (i % 11 == 0) {
                y++;
                x = 0;
            }
            invaders[i] = new Invader(x, y);
        }

    }

    private void createShields() {
        for (int i = 0; i < shields.length; i++) {
            shields[i] = new Shield(i);
        }
    }

    public void dispose() {
        megaTexture.dispose();
        batch.dispose();
        font.dispose();
        background.dispose();
    }

    public void resize(int width, int height) {
    }

    public void pause() {
        running = false;
    }

    public void resume() {
        running = true;
    }

}
